package cn.nexttec.noteplayer.common


import android.media.MediaCodec
import android.media.MediaExtractor
import android.media.MediaFormat
import android.util.Log
import java.io.File
import java.io.FileOutputStream
import java.nio.ByteBuffer

object AudioDecoderToPCM {

    private const val TAG = "AudioDecoderToPCM"

    /**
     * 从视频文件提取音频轨并解码为 PCM 原始音频数据
     * @param inputPath 视频文件路径（支持 mp4/mkv/webm）
     * @param outputPcmPath 输出 .pcm 文件路径
     */
    @Throws(Exception::class)
    fun decodeToPCM(inputPath: String, outputPcmPath: String) {
        val extractor = MediaExtractor()
        extractor.setDataSource(inputPath)

        var audioTrackIndex = -1
        var format: MediaFormat? = null

        // 找音频轨
        for (i in 0 until extractor.trackCount) {
            val f = extractor.getTrackFormat(i)
            val mime = f.getString(MediaFormat.KEY_MIME)
            if (mime != null && mime.startsWith("audio/")) {
                audioTrackIndex = i
                format = f
                break
            }
        }

        if (audioTrackIndex == -1 || format == null) {
            throw IllegalStateException("No audio track found in $inputPath")
        }

        extractor.selectTrack(audioTrackIndex)

        val mimeType = format.getString(MediaFormat.KEY_MIME)!!
        val codec = MediaCodec.createDecoderByType(mimeType)
        codec.configure(format, null, null, 0)
        codec.start()

        val inputBuffers = codec.inputBuffers
        val outputBuffers = codec.outputBuffers
        val bufferInfo = MediaCodec.BufferInfo()

        File(outputPcmPath).parentFile?.mkdirs()
        val outputStream = FileOutputStream(outputPcmPath)

        var isEOS = false
        val timeoutUs = 10000L

        while (true) {
            if (!isEOS) {
                val inputIndex = codec.dequeueInputBuffer(timeoutUs)
                if (inputIndex >= 0) {
                    val inputBuffer = inputBuffers[inputIndex]
                    val sampleSize = extractor.readSampleData(inputBuffer, 0)
                    Log.d("extractAudio","extracting:$sampleSize")
                    if (sampleSize < 0) {
                        codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
                        isEOS = true
                    } else {
                        val presentationTimeUs = extractor.sampleTime
                        codec.queueInputBuffer(inputIndex, 0, sampleSize, presentationTimeUs, 0)
                        extractor.advance()
                    }
                }
            }

            val outputIndex = codec.dequeueOutputBuffer(bufferInfo, timeoutUs)
            if (outputIndex >= 0) {
                val outputBuffer = outputBuffers[outputIndex]
                val chunk = ByteArray(bufferInfo.size)
                outputBuffer.get(chunk)
                outputBuffer.clear()

                outputStream.write(chunk)
                codec.releaseOutputBuffer(outputIndex, false)

                if (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
                    break
                }
            }
        }

        outputStream.close()
        codec.stop()
        codec.release()
        extractor.release()

        Log.i(TAG, "解码完成，PCM保存至：$outputPcmPath")
    }
}
